/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.core.windows;
import java.awt.Rectangle;
import java.awt.Image;
import java.awt.Frame;
import java.awt.Toolkit;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.util.Set;
import java.util.ArrayList;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.EventObject;
import java.awt.event.ComponentEvent;
import java.net.URL;
import javax.swing.SwingUtilities;
import org.openide.windows.*;
import org.openide.util.Mutex;
import org.openide.util.io.SafeException;
import org.openide.TopManager;
import org.netbeans.core.windows.util.*;
/** This class is an implementation of Mode interface.
* It's responsible for managing top component container.
* This implementation supports switching of various types of
* top component containers.
*
* @author Dafe Simonek
*/
public final class ModeImpl implements Mode, ContainerListener,
DeferredPerformer.DeferredCommand {
/** serial version UID */
static final long serialVersionUID = 2721445375634234372L;
/** Constant representing single type of the mode */
public static final int SINGLE = 1;
/** Constant representing multi tabbed type of the mode */
public static final int MULTI_TAB = 2;
/** For future use */
public static final int SIDE_BY_SIDE = 4;
/** For future use */
public static final int INTERNAL_FRAME = 8;
/** Top components changes property name */
public static final String PROP_TOP_COMPONENTS = "topComponents"; // NOI18N
/** Icon of the mode */
URL icon;
/** icon as an image, created from URL */
Image iconImage;
/** Programmatic unique name of the mode */
String name;
/** Human presentable name of the mode */
String displayName;
/** The bounds of the mode - should be kept synchronized with
* top component container when container exists and visible */
Rectangle bounds;
/** Current container type asociated with this mode */
int containerType;
/** true if this mode was created by user, not system */
boolean userDefined;
/** The workspace which this mode belongs to */
Workspace workspace;
/** Name of workspace which this mode belongs to.
* Used only during deserialization when delayed validation is needed */
String workspaceName;
/** Composited container for top components. Can be null if no top
* components are currently in this mode */
transient TopComponentContainer tcc;
/** Set which holds weak references to the top components which
* are docked in this mode but closed
* @associates WeakReference*/
transient HashSet closedComponents;
/** Asociation with window manager implementation */
private transient WindowManagerImpl wm;
/** asociated property change support for firing property changes */
private transient PropertyChangeSupport changeSupport;
/** helper variable, true when asociated top component container
* is showing on the screen, false otherwise */
private transient boolean showing;
/** helper variable, true when there is some pending focus request */
private transient boolean deferredFocusRequest;
/** helper variable, holds top component as context of pending
* focus request */
private transient TopComponent compToReceiveFocus;
/** Listener to the changes of the name of top component */
private transient NameListener nameListener;
/** Helper variable which holds */
private transient String oldDisplayName;
/** manager of versioned serialization */
private static VersionSerializator serializationManager;
/** Construct new mode with given properties */
public ModeImpl (String name, String displayName, URL icon,
int containerType, boolean userDefined,
Workspace workspace) {
this.name = name;
this.displayName = displayName;
this.icon = icon;
this.workspace = workspace;
this.containerType = containerType;
this.userDefined = userDefined;
initialize();
}
/** Creates new mode as a shallow copy of original mode on
* given workspace. New mode will have the same characterists,
* (displayname, icon, container type, bounds).
* Contained components are NOT taken from original.
* The name can differ (name uniquennes is ensured automatically).
*/
public ModeImpl (Workspace workspace, ModeImpl original) {
this(original.name, original.displayName, original.icon,
original.containerType, original.userDefined, workspace);
// set unigue name
if (workspace.findMode(name) != null) {
int i = 1;
while (workspace.findMode(name = original.name + "_" + i++) != null); // NOI18N
}
// bounds
this.bounds = (original.bounds == null) ? null
: new Rectangle(original.bounds);
}
/** Initialization, called from constructors and deserialization */
private void initialize () {
this.wm = (WindowManagerImpl)TopManager.getDefault().getWindowManager();
changeSupport = new PropertyChangeSupport(this);
}
/** Get the programmatic name of the mode.
* This name should be unique, as it is used to find modes etc.
* @return programmatic name of the mode
*/
public String getName () {
return name;
}
/* @return true if given top component can be docked to this mode,
* false otherwise */
public boolean canDock (TopComponent tc) {
return (tcc == null) ? true : tcc.canAdd(tc);
}
/** Attaches a component to a mode for this workspace.
* If the component is in different mode on this desktop, it is
* removed from the original and moved to this one.
*
* @param c top component to dock into this mode
* @return true if top component was succesfully docked to this
* mode, false otherwise */
public boolean dockInto (final TopComponent tc) {
if (!canDock(tc))
return false;
final ModeImpl mi = (ModeImpl)workspace.findMode(tc);
// find out if component is opened
boolean opened = wm.findManager(tc).isOpened(workspace);
// System.out.println("Tc in mode: " + ((mi == null) ? "null" : mi.getName())); // NOI18N
if ((mi != null) && (!this.equals(mi))) {
mi.release(tc);
}
if (opened) {
// compute mode bounds if not known yet
if (bounds == null) {
((WorkspaceImpl)workspace).placeMode(this, tc);
}
// remove top component in a case it was previously
// docked in this mode in closed state
removeClosedComponent(tc);
if (tcc == null)
createContainer();
// synchronize opening with AWT Event queue
Mutex.EVENT.readAccess(new Runnable () {
public void run () {
if (tcc.getState() == Frame.ICONIFIED) {
tcc.setState(Frame.NORMAL);
}
// add only if not re-opened multiple times
if (!this.equals(mi)) {
tcc.addTopComponent(tc);
updateNameListener();
}
// show container if we are on current workspace only
if (workspace.equals(wm.getCurrentWorkspace()))
setVisible(true);
//System.out.println(tc.getName() + " docked to " + getName()); // NOI18N
// notify
changeSupport.firePropertyChange(
PROP_TOP_COMPONENTS, null, null);
}
});
} else {
// component not opened
addClosedComponent(tc);
// notify
changeSupport.firePropertyChange(PROP_TOP_COMPONENTS, null, null);
}
return true;
}
/** Releases given top component from current association
* with this mode.
*/
public void release (TopComponent tc) {
// find out if component is opened
if (wm.findManager(tc).isOpened(workspace)) {
int left = tcc.removeTopComponent(tc);
if (left <= 0) {
destroyContainer();
} else {
updateNameListener();
}
} else {
removeClosedComponent(tc);
}
// notify
changeSupport.firePropertyChange(PROP_TOP_COMPONENTS, null, null);
}
/** Closes given top component.
* Closing here means removing from top component container and
* adding to the set of closed components docked in this mode.
*/
public void close (TopComponent tc) {
if (tcc.containsTopComponent(tc)) {
int left = tcc.removeTopComponent(tc);
if (left <= 0) {
destroyContainer();
} else {
updateNameListener();
}
addClosedComponent(tc);
}
// notify
changeSupport.firePropertyChange(PROP_TOP_COMPONENTS, null, null);
}
/** Closes this mode - it means, that opened top components
* are closed and closed components docked to this mode are
* removed
* @return true if mode was succesfully cleared and closed,
* false if some top component refused to close
*/
public boolean close () {
// clear closed components
if (closedComponents != null)
closedComponents.clear();
if (tcc == null)
return true;
// try to close all opened top components
// selected top component will be closed at last
// to prevent from focus transfering between components during closing
TopComponent[] tcs = tcc.getTopComponents();
TopComponent selected = tcc.getSelectedTopComponent();
boolean result = true;
for (int i = 0; i < tcs.length; i++) {
if ((!tcs[i].equals(selected)) && (!tcs[i].close(workspace))) {
result = false;
}
}
// close selected top component, if possible
if ((selected != null) && (!selected.close(workspace))) {
result = false;
}
return result;
}
/** Sets the bounds of the mode.
* @param s the bounds for the mode
*/
public void setBounds (Rectangle rect) {
if ((bounds != null) && (bounds.equals(rect))) {
return;
}
Rectangle old = bounds;
bounds = rect;
// notify top component container if possible
if (tcc != null) {
tcc.setBounds(bounds);
}
// notify others interested
changeSupport.firePropertyChange(PROP_BOUNDS, old, bounds);
}
/** Getter for current bounds of the mode.
* @return the bounds of the mode
*/
public Rectangle getBounds () {
return bounds;
}
/** Getter for asociated workspace.
* @return The workspace instance to which is this mode asociated.
*/
public Workspace getWorkspace () {
return workspace;
}
/** @return array of top components which are currently
* docked in this mode. May return empty array if no top component
* is docked in this mode.
*/
public TopComponent[] getTopComponents () {
TopComponent[] containerTcs =
(tcc == null) ? new TopComponent[0] : tcc.getTopComponents();
if (closedComponents == null)
return containerTcs;
// merge container and closed tcs into one array
TopComponent[] result = null;
synchronized (this) {
WeakReference[] closedRefs =
(WeakReference[])closedComponents.toArray(new WeakReference[0]);
HashSet closed = new HashSet(closedRefs.length);
TopComponent curTc = null;
for (int i = 0; i < closedRefs.length; i++) {
curTc = (TopComponent)closedRefs[i].get();
// remove from set if not valid reference
if (curTc != null)
closed.add(curTc);
else
closedComponents.remove(curTc);
}
// merge!
result = new TopComponent[containerTcs.length + closed.size()];
System.arraycopy(containerTcs, 0, result, 0, containerTcs.length);
System.arraycopy(closed.toArray(new TopComponent[closed.size()]), 0,
result, containerTcs.length, closed.size());
}
return result;
}
/** @return an array of opened top components currently
* docked in this mode.
*/
public TopComponent[] getOpenedTopComponents () {
return (tcc == null) ? new TopComponent[0] : tcc.getTopComponents();
}
/** The component requests focus. Request can be delayed
* if top component containe ris not in consistent state.
*/
public void requestFocus (TopComponent comp) {
if (!showing) {
deferredFocusRequest = true;
compToReceiveFocus = comp;
} else {
tcc.requestFocus(comp);
}
}
/** Requests focus for whole mode. Request can be delayed
* if top component containe ris not in consistent state.
*/
public void requestFocus () {
if (!showing) {
deferredFocusRequest = true;
} else {
tcc.requestFocus();
}
}
/** @return TopComponentContainer - that is JInternalFram for instane.
* Can return null if no container is asociated at present.
* (it means that no opened top component is docked in this mode) */
public TopComponentContainer getTopComponentContainer() {
return tcc;
}
/** @return Human presentable name of this mode implementation */
public String getDisplayName () {
return displayName;
}
/** Sets new display name of this mode */
public void setDisplayName (String s) {
if (s == displayName) {
return;
}
String old = displayName;
displayName = s;
changeSupport.firePropertyChange(PROP_DISPLAY_NAME, old, displayName);
}
/** @return icon of this mode */
public Image getIcon () {
if ((iconImage == null) && (icon != null)) {
try {
iconImage = Toolkit.getDefaultToolkit().getImage(icon);
} catch (Exception exc) {
// PENDING
// in jdk 1.3, strange exceptions are thrown for some
// reason that I couldn't find....ignore exceptions for now
}
}
return iconImage;
}
public URL getIconURL () {
return icon;
}
/** Updates UI of asociated top component container,
* if possible */
public void updateUI () {
if (tcc != null)
tcc.updateUI();
}
/** Sets the state of asociated top component container
*/
public void setState (int state) {
if (tcc != null)
tcc.setState(state);
}
/** Shows or hides asociated top component container,
* if possible (if container exists)
*/
public void setVisible (boolean state) {
if ((tcc != null) && (state != tcc.isVisible())) {
if (!state || shouldShowTcc()) {
tcc.setVisible(state);
}
}
}
/** @return true if it is ok to show top component container
* false otherwise (all top components haven't been opened yet)
* Called from setVisible.
*/
private boolean shouldShowTcc () {
TopComponent[] tcs = tcc.getTopComponents();
for (int i = 0; i < tcs.length; i++) {
if (WindowManagerImpl.findManager(tcs[i]).isOpened()) {
return true;
}
}
return false;
}
/** @return true if no component is docked to this mode
* or all components docked to this mode are closed */
public boolean isOrphan () {
return (tcc == null) || (tcc.getTopComponents().length <= 0);
}
/** @return true if this mode is currently in the state where
* it contains exactly one OPENED top component.
* (it can contains any number of closed components but this method
* will still return true if there is exatly one opened)
*/
public boolean isSingle () {
return (tcc != null) && (tcc.getTopComponents().length == 1);
}
/** @return true if mode is user defined, false otherwise
* (defined programmatically) */
public boolean isUserDefined () {
return userDefined;
}
/** Fills this mode with top components contained in given source
* mode.
*/
public void fillTopComponents (ModeImpl source) {
// copy references to closed top components
if (source.closedComponents != null) {
WeakReference curRef = null;
TopComponent curTc = null;
for (Iterator iter = source.closedComponents.iterator(); iter.hasNext(); ) {
curRef = (WeakReference)iter.next();
curTc = (TopComponent)curRef.get();
if (curTc != null) {
dockInto(curTc);
}
}
}
// copy references to opened top components (and reopen them)
TopComponent[] tcs = source.getOpenedTopComponents();
for (int i = 0; i < tcs.length; i++) {
dockInto(tcs[i]);
tcs[i].open(workspace);
}
}
/**** Implementation of container listener - we listen to the
* events in container and react properly */
/** When container is being deactivated */
public void containerDeactivated (EventObject eo) {
}
/** When container was closed */
public void containerClosed (EventObject eo) {
}
/** When container was brought bacjk from icon to normal state */
public void containerDeiconified (EventObject eo) {
}
/** When container was opened - showed.
* Checks if there are some pending focus requests and if so,
* calls one of the requestFocus methods properly */
public void containerOpened (EventObject eo) {
}
/** When container was iconified */
public void containerIconified (EventObject eo) {
}
/** User attempted to close the container.
* So try to close all contained top components, if they agree.
*/
public void containerClosing (EventObject eo) {
TopComponent[] tcs = tcc.getTopComponents();
TopComponent selected = tcc.getSelectedTopComponent();
boolean shouldClose = true;
for (int i = 0; i < tcs.length; i++) {
if ((!tcs[i].equals(selected)) && (!tcs[i].close())) {
shouldClose = false;
}
}
// close selected top component, if possible
if ((selected != null) && (!selected.close())) {
shouldClose = false;
}
// close container if nothing left
if (shouldClose) {
destroyContainer();
}
}
/** When container was made active - receives focus */
public void containerActivated (EventObject eo) {
}
/** When container was resized, its size was changed */
public void containerResized (ComponentEvent ce) {
setBounds(ce.getComponent().getBounds());
}
/** When container was moved, its position was changed */
public void containerMoved (ComponentEvent ce) {
setBounds(ce.getComponent().getBounds());
}
/** Called when container was shown. */
public void containerShown (ComponentEvent ce) {
showing = true;
if (deferredFocusRequest) {
deferredFocusRequest = false;
if (compToReceiveFocus != null) {
requestFocus(compToReceiveFocus);
compToReceiveFocus = null;
} else {
requestFocus();
}
}
}
/** Called when container was hidden. */
public void containerHidden (ComponentEvent ce) {
showing = false;
}
/** Sets new container type and transfers content
* of current container to the new one
* @return true if new container was switched succesfully
*/
public boolean setContainerType (int containerType) {
this.containerType = containerType;
// PENDING - to be done - create new container, transfer components
// destroy old one if component container already exist
return true;
}
/** @return current container type */
public int getContainerType () {
return containerType;
}
/** Add listener to the property changes */
public void addPropertyChangeListener (PropertyChangeListener pchl) {
changeSupport.addPropertyChangeListener(pchl);
}
/** Remove listener to the property changes */
public void removePropertyChangeListener (PropertyChangeListener pchl) {
changeSupport.removePropertyChangeListener(pchl);
}
/** Adds top component to the set of closed tcs docked
* in this mode */
void addClosedComponent (TopComponent tc) {
if (closedComponents == null)
closedComponents = new HashSet(10);
closedComponents.add(new WeakReference(tc));
}
/** Removes top component from the set of closed tcs docked
* in this mode */
void removeClosedComponent (TopComponent tc) {
if (closedComponents == null)
return;
TopComponent curTc = null;
// remove found item plus all garbage collected
WeakReference[] weakRefs =
(WeakReference[])closedComponents.toArray(new WeakReference[0]);
for (int i = 0; i < weakRefs.length; i++) {
curTc = (TopComponent)weakRefs[i].get();
if ((curTc == null) || (curTc.equals(tc)))
closedComponents.remove(weakRefs[i]);
}
}
/** @return Newly created top component container */
synchronized void createContainer () {
if (tcc != null)
return;
switch (containerType) {
case SINGLE:
tcc = new MultiTabContainer(this);
((MultiTabContainer)tcc).setMaxCount(1);
break;
case MULTI_TAB:
tcc = new MultiTabContainer(this);
break;
case SIDE_BY_SIDE:
// not implemented yet
break;
case INTERNAL_FRAME:
// not implemented yet
break;
}
tcc.addContainerListener(this);
}
/** Destroys asociated top component container */
void destroyContainer () {
if (tcc == null)
return;
updateNameListener ();
tcc.removeContainerListener(this);
tcc.dispose();
tcc = null;
}
/** Asigns or removes listener to the name of the top component.
* If mode is single, its display name should be the same as
* the name of contained component. */
private void updateNameListener () {
if (isSingle()) {
if (nameListener == null) {
nameListener = new NameListener();
}
// save display name before listener activation
oldDisplayName = displayName;
nameListener.activate();
} else {
if (nameListener != null) {
nameListener.passivate();
if ((oldDisplayName != null) && !"".equals(oldDisplayName.trim())) { //NOI18N
setDisplayName(oldDisplayName);
}
}
}
}
/** Just for testing...
*/
protected void finalize () throws Throwable {
// System.out.println ("Finalizing Mode: " + name); // NOI18N
super.finalize();
}
/** Accessor to the versioned serialization manager */
private VersionSerializator serializationManager () {
if (serializationManager == null) {
serializationManager = createSerializationManager();
}
return serializationManager;
}
/** Creates new serialization manager filled with our versions */
private static VersionSerializator createSerializationManager () {
VersionSerializator result = new VersionSerializator();
result.putVersion(new Version1());
return result;
}
/** Let instance of properly parametrized DefaultReplacer to keep
* persistent state of this workspace
*/
private Object writeReplace ()
throws ObjectStreamException {
// provide version with data
Version1 version =
(Version1)serializationManager().getVersion(Version1.NAME);
version.assignData(this);
// use replacer
return new DefaultReplacer(new VSAccess(serializationManager()));
}
/** Called when first phase of WS deserialization is done.
* Validates asociation with its workspace.
*/
void validateSelf (Workspace workspace) {
this.workspace = workspace;
/*if (workspace == null) {
workspace = TopManager.getDefault().getWindowManager().
findWorkspace(workspaceName);
}*/
}
/** Called when first phase of WS deserialization is done.
* Validates its top component container, if possible
*/
void validateData () {
// validate tcc, if possible
if (tcc != null) {
tcc.validateData();
if (tcc.getTopComponents().length > 0) {
tcc.addContainerListener(this);
// put a request for reopening all top components in
// the container (actual opening is delayed and performed
// after deserializaton)
TopComponent[] tcs = tcc.getTopComponents();
DeferredOpenContext openContext = null;
for (int i = 0; i < tcs.length; i++) {
openContext = new DeferredOpenContext();
openContext.tc = tcs[i];
openContext.workspace = workspace;
WindowManagerImpl.deferredPerformer().putRequest(this, openContext);
}
} else {
tcc = null;
}
}
}
/** Implementation of DeferredPerformer.DeferredCommand interface.
* Actually opens managed top component. */
public void performCommand (Object context) {
DeferredOpenContext openContext = (DeferredOpenContext)context;
openContext.tc.open(openContext.workspace);
}
/** Holds data context for delayed opening */
private static final class DeferredOpenContext {
TopComponent tc;
Workspace workspace;
}
/** Basic version of persistence for mode implementation.
* Method assignData(modeImpl) must be called prior to serialization */
private static final class Version1
implements DefaultReplacer.ResVersionable {
/* identification string */
public static final String NAME = "Version_1.0"; // NOI18N
/** variables of persistent state of the mode implementation */
String name;
String displayName;
Rectangle bounds;
URL icon;
int containerType;
boolean userDefined;
String workspaceName;
TopComponentContainer tcc;
/** asociation with mode implementation, used when writing */
ModeImpl mode;
/** Identification of the version */
public String getName () {
return "Version_1.0"; // NOI18N
}
/** Assigns data to be written. Must be called before writing */
public void assignData (ModeImpl mode) {
this.mode = mode;
}
/** read the data of the version from given input */
public void readData (ObjectInput in)
throws IOException, ClassNotFoundException {
// read mode fields
name = (String)in.readObject();
displayName = (String)in.readObject();
bounds = (Rectangle)in.readObject();
icon = (URL)in.readObject();
containerType = ((Integer)in.readObject()).intValue();
userDefined = ((Boolean)in.readObject()).booleanValue();
workspaceName = (String)in.readObject();
tcc = (TopComponentContainer)in.readObject();
}
/** write the data of the version to given output */
public void writeData (ObjectOutput out)
throws IOException {
// write mode fields
out.writeObject(mode.name);
out.writeObject(mode.displayName);
out.writeObject(mode.bounds);
out.writeObject(mode.icon);
out.writeObject(new Integer(mode.containerType));
out.writeObject(new Boolean(mode.userDefined));
out.writeObject(mode.workspace.getName());
out.writeObject(mode.tcc);
}
public Object resolveData ()
throws ObjectStreamException {
Workspace workspace =
TopManager.getDefault().getWindowManager().findWorkspace(workspaceName);
ModeImpl result =
(workspace == null) ? null : (ModeImpl)workspace.findMode(name);
if (result == null) {
// mode don't exist, create new one and fill it
result = new ModeImpl(name, displayName, icon, containerType,
userDefined, workspace);
result.bounds = bounds;
result.tcc = tcc;
// assign workspace if needed for later validation
if (workspace == null) {
result.workspaceName = workspaceName;
}
}
return result;
}
} // end of Version1 inner class
/** Implementation of persistent access to our version serializator */
private static final class VSAccess implements DefaultReplacer.Access {
/** version serializator, used only during writing */
transient VersionSerializator vs;
/** serialVersionUID */
private static final long serialVersionUID = -7577235918945664917L;
public VSAccess (VersionSerializator vs) {
this.vs = vs;
}
public VersionSerializator getVersionSerializator () {
return (vs == null) ? createSerializationManager() : vs;
}
} // end of VSAccess inner class
private final class NameListener implements PropertyChangeListener {
WindowManagerImpl.TopComponentManager tcm;
void activate () {
if (tcm == null) {
tcm = wm.findManager(tcc.getTopComponents()[0]);
tcm.addPropertyChangeListener(this);
}
}
void passivate () {
if (tcm != null) {
tcm.removePropertyChangeListener(this);
tcm = null;
}
}
public void propertyChange (PropertyChangeEvent evt) {
String propName = evt.getPropertyName();
if (WindowManagerImpl.TopComponentManager.PROP_NAME.equals(propName)) {
// name of top component changed, update display name of the mode
setDisplayName(tcm.getComponent().getName());
}
}
} // end of NameListener inner class
}
/*
* Log
* 30 Gandalf 1.29 1/17/00 David Simonek topcomponent.open upon
* deserialization now delayed automatically
* 29 Gandalf 1.28 1/16/00 Jaroslav Tulach Memory Leak Fix.
* 28 Gandalf 1.27 1/15/00 David Simonek mutliwindow title bug
* fixed
* 27 Gandalf 1.26 1/13/00 David Simonek i18n
* 26 Gandalf 1.25 1/12/00 Ian Formanek NOI18N
* 25 Gandalf 1.24 12/17/99 David Simonek #1913, #2970
* 24 Gandalf 1.23 11/30/99 David Simonek neccessary changes needed
* to change main explorer to new UI style (tabs are full top components
* now, visual workspace added, layout of editing workspace chnaged a bit)
* 23 Gandalf 1.22 11/6/99 David Simonek serialization bug fixing
* 22 Gandalf 1.21 11/4/99 David Simonek ws serialization bugfixes
* 21 Gandalf 1.20 11/3/99 David Simonek completely rewritten
* serialization of windowing system...
* 20 Gandalf 1.19 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 19 Gandalf 1.18 10/6/99 David Simonek more robust serialization
* of window system (especially editor TCs)
* 18 Gandalf 1.17 9/13/99 David Simonek request focus for the
* mode added
* 17 Gandalf 1.16 8/15/99 David Simonek initialization in
* readObject() returned back (how could it dissapear??)
* 16 Gandalf 1.15 8/14/99 David Simonek bugfixes, #3347, #3274
* etc.
* 15 Gandalf 1.14 8/10/99 Ian Formanek removed debug printlns
* 14 Gandalf 1.13 8/9/99 David Simonek
* 13 Gandalf 1.12 7/31/99 David Simonek small additions
* 12 Gandalf 1.11 7/30/99 David Simonek multiple serialization
* bugfix
* 11 Gandalf 1.10 7/30/99 David Simonek serialization fixes
* 10 Gandalf 1.9 7/29/99 David Simonek further ws serialization
* changes
* 9 Gandalf 1.8 7/28/99 David Simonek workspace serialization
* bugfixes
* 8 Gandalf 1.7 7/28/99 David Simonek serialization of window
* system...first draft :-)
* 7 Gandalf 1.6 7/23/99 David Simonek another fixes (closing a
* component)
* 6 Gandalf 1.5 7/21/99 David Simonek
* 5 Gandalf 1.4 7/21/99 David Simonek window system updates...
* 4 Gandalf 1.3 7/20/99 David Simonek various window system
* updates
* 3 Gandalf 1.2 7/14/99 Ales Novak bugfixes
* 2 Gandalf 1.1 7/12/99 Jaroslav Tulach To be compilable.
* 1 Gandalf 1.0 7/11/99 David Simonek
* $
*/